package br.ita.comp.ces22.quiz.email.adapter.commons;

import java.net.URL;
import java.util.Map;

import javax.activation.URLDataSource;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;

import br.ita.comp.ces22.quiz.email.adapter.EmailAdapter;
import br.ita.comp.ces22.quiz.email.exception.EmailAdapterException;

/**
 * Apache Commons Mail based implementation of {@link EmailAdapter}
 * 
 * @author Diego
 */
public class CommonsEmailAdapterImpl implements EmailAdapter {
    //private final Logger logger = Logger.getLogger(this.getClass());
    
    private boolean debug;
    private boolean usingTLS;
    private boolean usingSSL;
    
    private String hostName;
    private int smtpPort = 25;

    private String userName;
    private String password;

    private String fromAddress;
    private String fromName;
    
    private String bounceAddress;

	/**
     * Set the debug enabled flag
     * @param debug is debug enabled
     */
    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    /**
     * Get the debug enabled flag
     * @return is debug enabled
     */
    public boolean isDebug() {
        return debug;
    }


    /**
     * Set this to use TLS encrypted connection
     * @param usingTLS use TLS in connection
     */
    public void setUsingTLS(boolean usingTLS) {
        this.usingTLS = usingTLS;
    }

    /**
     * Verifies if is using TLS in connections
     * @return is using TLS in connections
     */
    public boolean isUsingTLS() {
        return usingTLS;
    }


    /**
     * Set this to use SSL encrypted connection
     * @param usingSSL use SSL in connection
     */
    public void setUsingSSL(boolean usingSSL) {
        this.usingSSL = usingSSL;
    }

    /**
     * Verifies if is using SSL in connections
     * @return is using SSL in connections
     */
    public boolean isUsingSSL() {
        return usingSSL;
    }


    /**
     * Configures the user account that will be used to send e-mails
     * @param userName the user of the SMTP host
     */
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * Get the already configured user to use
     * @return the user account
     */
    public String getUserName() {
        return userName;
    }


    /**
     * Configures the password of the already configured user account
     * @param password the password of the user
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Get the already configured password to use 
     * @return the password of the user
     */
    public String getPassword() {
        return password;
    }


    /**
     * Configures the SMTP host name
     * @param hostName the host to use
     */
    public void setHostName(String hostName) {
        this.hostName = hostName;
    }

    /**
     * Get the STMP host name
     * @return the used host
     */
    public String getHostName() {
        return hostName;
    }


    /**
     * Configures the SMTP port (Default: 25)
     * @param smtpPort the host port
     */
    public void setSmtpPort(int smtpPort) {
        this.smtpPort = smtpPort;
    }

    /**
     * Get the SMTP port
     * @return the used SMTP port
     */
    public int getSmtpPort() {
        return smtpPort;
    }


    /**
     * Defines the sender e-mail address of all subsequent messages
     * @param fromAddress the e-mail address of the sender
     */
    public void setFromAddress(String fromAddress) {
        this.fromAddress = fromAddress;
    }
    
    /**
     * Get the sender address
     * @return the sender address
     */
    public String getFromAddress() {
        return fromAddress;
    }


    /**
     * Defines the sender of all subsequent messages
     * @param fromName the sender of all messages
     */
    public void setFromName(String fromName) {
        this.fromName = fromName;
    }

    /**
     * Get the sender
     * @return the sender name
     */
    public String getFromName() {
        return fromName;
    }
    
    /**
     * Get the bounce address
     * @return the bounce address
     */
    public String getBounceAddress() {
		return bounceAddress;
	}

    /**
     * Defines the bounce address of all subsequent messages
     * @param bounceAddress the bounce address of all messages
     */
	public void setBounceAddress(String bounceAddress) {
		this.bounceAddress = bounceAddress;
	}


    /**
     * Configures the e-mail with the already defined settings
     * @param email the email to configure
     * @throws EmailException Any exception throw during the process
     */
    private void configure(Email email) throws EmailException {
        email.setDebug(isDebug());
        email.setTLS(isUsingTLS());
        email.setSSL(isUsingSSL());
        email.setHostName(getHostName());
        if (isUsingSSL())
            email.setSslSmtpPort(Integer.toString(getSmtpPort()));
        else
            email.setSmtpPort(getSmtpPort());

        if (getUserName() != null && getPassword() != null)
            email.setAuthentication(getUserName(), getPassword());

        email.setFrom(getFromAddress(), getFromName());
        email.setBounceAddress(bounceAddress);
    }
    
    /**
     * {@inheritDoc}
     */
    public String sendEmail(String toAddress, String content, String subject) throws EmailAdapterException {
        return sendEmail(toAddress, content, subject, null);
    }

    /**
     * {@inheritDoc}
     */
    public String sendEmail(String toAddress, String content, String subject, Map<String, URL> attachments) throws EmailAdapterException {
        HtmlEmail email = new HtmlEmail();
        try {
            configure(email);
            email.setHtmlMsg(content);
            email.addTo(toAddress);
            email.setSubject(subject);
            if (attachments != null) {
                for(String cid : attachments.keySet()) {
/*                    if (logger.isDebugEnabled()){
                    	logger.debug("Attaching URL: " + attachments.get(cid) + ", with cid: " + cid);
                    }*/
                    email.embed(attachments.get(cid), cid);
                    URLDataSource ds = new URLDataSource(attachments.get(cid));
	                email.embed(ds, cid, cid);
                }
            }
/*            if (logger.isDebugEnabled())
                logger.debug("Sending e-mail to: " + toAddress + ", subject: " + subject);*/
            return email.send();
        } catch(EmailException ex) {
            throw new EmailAdapterException(ex);
        }
    }
}